/**
 * @author temujin Oct 30, 2011
 */
package paim.gh.app;


import java.awt.Color;
import java.awt.Font;
import java.util.Observable;
import java.util.Observer;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.SwingConstants;
import javax.swing.tree.TreePath;

import paim.wingchun.model.pojos.Pojo;
import paim.wingchun.view.componentes.toolbar.JExtraTools;
import paim.wingchun.view.componentes.toolbar.JNavegador;

import paim.gh.controller.eventos.ArvoreEvent;
import paim.gh.controller.eventos.PropriedadesEvent;
import paim.gh.model.pojos.Aula;
import paim.gh.model.pojos.Grade;
import paim.gh.model.pojos.Professor;
import paim.gh.model.pojos.Turma;
import paim.gh.view.paineis.arvore.Arvore;
import paim.gh.view.paineis.arvore.ArvoreListener;
import paim.gh.view.paineis.arvore.ArvoreNode;
import paim.gh.view.paineis.filtros.PainelFiltros;
import paim.gh.view.paineis.propriedades.PainelPropriedades;
import paim.gh.view.paineis.toolBar.GradeTools;

/**
 * Classe responsavel por interagir informacoes entre os paineis principais
 *
 * @author temujin Oct 30, 2011
 */
public final class Gerenciador implements Observer, Gerenciavel {

    private static Gerenciador instancia;

    private PainelPropriedades painelPropriedades;

    private PainelFiltros painelFiltros;

    private Arvore arvore;

    private GradeTools gradeTools;

    private JNavegador navegador;

    private JExtraTools extraTools;

    private Pojo selecionado;

    public static Gerenciador getInstancia() {
        if ( instancia == null )
            instancia = new Gerenciador();
        return instancia;
    }

    private Gerenciador() {
        initialize();
    }

    private void initialize() {
        initToolBar();
        initStatus();
        initArvoreLateral();
        initPainelPropriedades();
        initPainelFiltros();
    }

    // TODO deveria tem um atributo indicando o objeto selecionado, se for grade, professor aula ou turma, que serao
    // efetivamente os objetos que deverao interferir em todos os paineis, OK vou fazer isso agora

    @Override
    public void setListeners() {
        ArvoreEvent arvoreEvent = new ArvoreEvent(getArvore());
        getArvore().addListener((ArvoreListener) arvoreEvent);
        arvoreEvent.addObserver(Gerenciador.this);
        arvoreEvent.addObserver(Gradiador.getInstance());

        PropriedadesEvent propriedadesEvent = new PropriedadesEvent();
        getPainelPropriedades().addListener(propriedadesEvent);

        // getPainelPropriedades().addPropriedadesListener(new PropriedadesListener() {
        //
        // @Override
        // public void actionPerformed(ActionEvent e) {
        //
        // JButtonConstrutor asd = (JButtonConstrutor) e.getSource();
        // System.out.println("lkjhlkhlkjh");
        //
        // }
        // });
    }

    /**
     * @author paim 07/03/2012 void
     */
    private void initStatus() {
        JPanel areaStatus = GHApp.getInstancia().getVisaoApp().getjAreaStatus();

    }

    /**
     * @author paim 07/03/2012 void
     */
    private void initToolBar() {
        JToolBar toolBar = GHApp.getInstancia().getVisaoApp().getjToolBar();
        toolBar.add(Box.createHorizontalGlue());
        toolBar.add(getGradeTools());
        toolBar.addSeparator();
        toolBar.add(getNavegador());
        toolBar.addSeparator();
        toolBar.add(getExtraTools());
    }

    /**
     * @author paim 07/03/2012 void
     */
    private void initArvoreLateral() {
        JScrollPane scrollPane = GHApp.getInstancia().getVisaoApp().getjAreaArvore();
        /* adiciono a arvore */
        scrollPane.setViewportView(getArvore());

        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setBackground(Color.BLACK);
    }

    /**
     * @author temujin Feb 27, 2012 void
     */
    private void initPainelPropriedades() {
        JScrollPane scrollPane = GHApp.getInstancia().getVisaoApp().getjAreaPropriedades();
        /* adicionando o painel ao ScrollPane das propriedades */
        scrollPane.setViewportView(getPainelPropriedades());

        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setBackground(Color.BLACK);
        // jAreaPropriedades.setRowHeaderView(new JLabel("setRowHeaderView"));

        JLabel headerView = new JLabel("Propriedades");
        headerView.setHorizontalAlignment(SwingConstants.CENTER);
        headerView.setHorizontalAlignment(SwingConstants.CENTER);
        headerView.setFont(new Font("Tahoma", Font.ITALIC, 11));
        headerView.setForeground(Color.BLUE);
        headerView.setBackground(Color.BLACK);

        scrollPane.setColumnHeaderView(headerView);

    }

    /**
     * @author paim 07/03/2012 void
     */
    private void initPainelFiltros() {
        GHApp.getInstancia().getVisaoApp().getjAreaFiltros().add(getPainelFiltros());
    }

    void setSelectedNode(TreePath path) {
        getArvore().setSelectionPath(path);
    }

    ArvoreNode getSelectedNode() {
        return (ArvoreNode) getArvore().getLastSelectedPathComponent();
    }

    @Deprecated
    public void jTreeRepaint() {
        Arvore arvore = Gerenciador.getInstancia().getArvore();
        // Arvore arvore = GHApp.getInstancia().getVisaoApp().getSideTree();
        arvore.revalidate();
        arvore.repaint();

    }

    GradeTools getGradeTools() {
        if ( gradeTools == null ) {
            gradeTools = new GradeTools();
        }
        return gradeTools;
    }

    private JNavegador getNavegador() {
        if ( navegador == null ) {
            navegador = new JNavegador();
        }
        return navegador;
    }

    private JExtraTools getExtraTools() {
        if ( extraTools == null ) {
            extraTools = new JExtraTools();
        }
        return extraTools;
    }

    public Arvore getArvore() {
        if ( arvore == null ) {
            arvore = new Arvore();
            arvore.setExpandsSelectedPaths(true);

        }
        return arvore;
    }

    public PainelPropriedades getPainelPropriedades() {
        if ( painelPropriedades == null ) {
            painelPropriedades = new PainelPropriedades();

        }
        return painelPropriedades;
    }

    /**
     * @author paim 07/03/2012 void
     */
    public PainelFiltros getPainelFiltros() {
        if ( painelFiltros == null ) {
            painelFiltros = new PainelFiltros();
            painelFiltros.setBorder(BorderFactory.createLoweredBevelBorder());
        }
        return painelFiltros;
    }

    /**
     * @author temujin
     * @param
     */
    private void updatePropriedades(ArvoreNode nodo) {
        // XXX nao simplificar ainda, acho que podera ter mais coisas nesse metodo, se nao tiver, en tao deixar
        // implementacao dentro do update mesmo
        Class<? extends Pojo> classe = nodo.getClasse();

        Pojo pojo = nodo.getObjeto();

        if ( Grade.class.isAssignableFrom(classe) ) {
            getPainelPropriedades().show((Grade) pojo);
        }
        else if ( Turma.class.isAssignableFrom(classe) && nodo.isNodeObjeto() ) {
            getPainelPropriedades().show((Turma) pojo);
        }
        else if ( Aula.class.isAssignableFrom(classe) && nodo.isNodeObjeto() ) {
            getPainelPropriedades().show((Aula) pojo);
        }
        else if ( Professor.class.isAssignableFrom(classe) && nodo.isNodeObjeto() ) {
            getPainelPropriedades().show((Professor) pojo);
        }
        else {
            getPainelPropriedades().showEmpty();
        }
    }

    /**
     * @author paim 07/03/2012 void
     */
    private void updateFiltros() {
        // TODO Auto-generated method stub

    }

    private void updateStatus() {

    }

    private Pojo objetoGrade;

    @Override
    public void update(Observable observable, Object args) {

        if ( ArvoreEvent.class.isAssignableFrom(observable.getClass()) ) {
            Enum<?> enumEvento = (Enum<?>) ((Object[]) args)[0];
            ArvoreNode nodoSelecionado = (ArvoreNode) ((Object[]) args)[1];

            if ( Arvore.Eventos.SELECAO.equals(enumEvento) ) {
                setSelecionado(nodoSelecionado.getObjeto());
                updatePropriedades(nodoSelecionado);
                // TODO deve alterar visao da grade, filtros e sei la mais o que
            }
        }
    }

    @Deprecated
    public Pojo getObjetoGrade() {
        return objetoGrade;
    }

    public final Pojo getSelecionado() {
        return this.selecionado;
    }

    public final void setSelecionado(Pojo selecionado) {
        this.selecionado = selecionado;
    }

}
